﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Routing;
using EPiMVC.Routing;
using EPiMVC.UrlRewriting;
using EPiServer.Core;
using Moq;
using Xunit;

namespace EPiMVC.Tests.EPiServerRouteTests
{
    public class GetVirtualPathCalledWithRouteValues
    {
        [Fact]
        public void ContainingPageReferenceForMvcPage_ReturnsFriendlyUrl()
        {
            string friendlyUrl = "en/article/";
            RequestContext context = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
            RouteValueDictionary routeValues = new RouteValueDictionary();
            PageReference pageLink = new PageReference(123);
            routeValues.Add(EPiServerRoute.PageReferenceKey, pageLink);
            RouteConfiguration configuration = new RouteConfiguration();
            Mock<IPageResolver> fakeResolver = new Mock<IPageResolver>();
            fakeResolver.Setup(r => r.GetFriendlyUrl(pageLink)).Returns(friendlyUrl);
            configuration.PageResolver = fakeResolver.Object;
            EPiServerRoute route = new EPiServerRoute(configuration);
            Mock<IPageSource> fakeDataFactory = new Mock<IPageSource>();
            fakeDataFactory.Setup(d => d.GetPage(pageLink)).Returns(new PageData());
            route.DataFactory = fakeDataFactory.Object;

            VirtualPathData result = route.GetVirtualPath(context, routeValues);

            Assert.NotNull(result);
            Assert.NotNull(result.VirtualPath);
            Assert.Equal<string>(friendlyUrl, result.VirtualPath);
        }

        [Fact]
        public void NotContainingPageReference_ReturnsNull()
        {
            RequestContext context = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
            RouteValueDictionary routeValues = new RouteValueDictionary();

            EPiServerRoute route = new EPiServerRoute();
            VirtualPathData result = route.GetVirtualPath(context, routeValues);

            Assert.Null(result);
        }

        [Fact]
        public void ContainingPageReferenceOfInvalidType_ReturnsNull()
        {
            RequestContext context = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
            RouteValueDictionary routeValues = new RouteValueDictionary();
            routeValues.Add(EPiServerRoute.PageReferenceKey, new object());

            EPiServerRoute route = new EPiServerRoute();
            VirtualPathData result = route.GetVirtualPath(context, routeValues);

            Assert.Null(result);
        }

        [Fact]
        public void ContainingPageReferenceAndParameter_ReturnsFriendlyUrlWithParameterInQueryString()
        {
            string friendlyUrl = "en/article/";
            RequestContext context = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
            RouteValueDictionary routeValues = new RouteValueDictionary();
            PageReference pageLink = new PageReference(123);
            routeValues.Add(EPiServerRoute.PageReferenceKey, pageLink);
            string parameterName = "param";
            string parameterValue = "123";
            routeValues.Add(parameterName, parameterValue);
            RouteConfiguration configuration = new RouteConfiguration();
            Mock<IPageResolver> fakeResolver = new Mock<IPageResolver>();
            fakeResolver.Setup(r => r.GetFriendlyUrl(pageLink)).Returns(friendlyUrl);
            configuration.PageResolver = fakeResolver.Object;
            EPiServerRoute route = new EPiServerRoute(configuration);
            Mock<IPageSource> fakeDataFactory = new Mock<IPageSource>();
            fakeDataFactory.Setup(d => d.GetPage(pageLink)).Returns(new PageData());
            route.DataFactory = fakeDataFactory.Object;
            
            VirtualPathData result = route.GetVirtualPath(context, routeValues);

            Assert.NotNull(result);
            Assert.NotNull(result.VirtualPath);
            string expectedVirtualPath = string.Format("{0}?{1}={2}", friendlyUrl, parameterName, parameterValue);
            Assert.Equal<string>(expectedVirtualPath, result.VirtualPath);
        }

        [MvcPage]
        [RouteEnding("action/commentId")]
        private class RouteEndingPageData : PageData
        {
        }

        [Fact]
        public void ContainingPageReferenceToPageWithRouteEndingPageAndParameter_ReturnsFriendlyUrlWithParameterAsUrlSegment()
        {
            string friendlyUrl = "en/article/";
            RequestContext context = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
            RouteValueDictionary routeValues = new RouteValueDictionary();
            PageReference pageLink = new PageReference(123);
            routeValues.Add(EPiServerRoute.PageReferenceKey, pageLink);
            string parameterName = "action";
            string parameterValue = "view";
            routeValues.Add(parameterName, parameterValue);
            RouteConfiguration configuration = new RouteConfiguration();
            Mock<IPageResolver> fakeResolver = new Mock<IPageResolver>();
            fakeResolver.Setup(r => r.GetFriendlyUrl(pageLink)).Returns(friendlyUrl);
            configuration.PageResolver = fakeResolver.Object;
            EPiServerRoute route = new EPiServerRoute(configuration);
            Mock<IPageSource> fakeDataFactory = new Mock<IPageSource>();
            fakeDataFactory.Setup(d => d.GetPage(pageLink)).Returns(new RouteEndingPageData());
            route.DataFactory = fakeDataFactory.Object;

            VirtualPathData result = route.GetVirtualPath(context, routeValues);

            Assert.NotNull(result);
            Assert.NotNull(result.VirtualPath);
            string expectedVirtualPath = string.Format("{0}{1}/", friendlyUrl, parameterValue);
            Assert.Equal<string>(expectedVirtualPath, result.VirtualPath);
        }

        [Fact]
        public void ContainingControllerAndPageReference_ReturnsNull()
        {
            RequestContext context = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
            RouteValueDictionary routeValues = new RouteValueDictionary();
            routeValues.Add("controller", "whatever");
            routeValues.Add(EPiServerRoute.PageReferenceKey, new PageReference());

            EPiServerRoute route = new EPiServerRoute();
            VirtualPathData result = route.GetVirtualPath(context, routeValues);

            Assert.Null(result);
        }
    }
}
